package com.tiange.tgrandomcode.service.impl;

import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.tiange.tgrandomcode.entity.RandomCode;
import com.tiange.tgrandomcode.enums.RandomCodeEnum;
import com.tiange.tgrandomcode.service.RandomCodeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class RandomCodeServiceImpl implements RandomCodeService {

    @Value(value = "${isRandom}")
    private boolean isRandom;

    @Override
    public void exportRandomCode(ServletOutputStream outputStream, List<RandomCode> randomCodeList) {
        //所有的随机码
        List<String> randomAfterList = randomCodeList.stream().map(RandomCode::getRandomAfter).collect(Collectors.toList());

        //去掉导入的随机码中的空值
        List<RandomCode> randomCodeNotNullList = randomCodeList.stream().filter(randomCode -> StringUtils.isNotBlank(randomCode.getRandomImport()))
                .collect(Collectors.toList());

        //获得字母的List
        String ziMu = randomCodeNotNullList.get(0).getZm();
        Set<String> ziMuSet = new HashSet<>(Arrays.asList(ziMu.split("")));
        List<String> ziMuList = new ArrayList<>(ziMuSet);

        //判断需要修改的带?的随机码是否重复
        Set<String> randomImportSet = randomCodeNotNullList.stream().map(RandomCode::getRandomImport).collect(Collectors.toSet());
        List<String> randomImportList= randomCodeNotNullList.stream().map(RandomCode::getRandomImport).collect(Collectors.toList());
        if (randomImportSet.size() != randomImportList.size()){
            log.info("=====================》需要修改的带?的随机码有重复");
            return;
        }

        //需要修改的带?的随机码,Key为需要修改的带?的随机码，value为生成的数量
        Map<String, Integer> randomImportMap = randomCodeNotNullList.stream().collect(Collectors.toMap(
                RandomCode::getRandomImport,
                RandomCode::getNum
        ));

        List<String> randomExportList = new ArrayList<>();//输出的结果List

        if (isRandom){
            Random random = new Random();
            for (Map.Entry<String, Integer> randomImportEntry : randomImportMap.entrySet()) {
                int i = 0;
                this.random(i, randomImportEntry.getValue(), randomImportEntry.getKey(),
                        ziMuList, randomExportList, random, randomAfterList);
            }
        }else {
            this.notRandom(randomCodeNotNullList, ziMuList, randomExportList, randomAfterList);
        }

        this.listToMap(randomCodeList, outputStream, randomExportList);
    }

    private void listToMap(List<RandomCode> randomCodeList, ServletOutputStream outputStream, List<String> randomExportList) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        if (randomCodeList.size() > randomExportList.size()){
            int i = 0;
            for (RandomCode randomCode : randomCodeList) {
                Map<String, Object> map = new LinkedHashMap<>();
                map.put(RandomCodeEnum.RANDOM_AFTER.getDesc(), randomCode.getRandomAfter());
                map.put(RandomCodeEnum.ZM.getDesc(), randomCode.getZm());
                map.put(RandomCodeEnum.RANDOM_IMPORT.getDesc(), randomCode.getRandomImport());
                map.put(RandomCodeEnum.NUM.getDesc(), randomCode.getNum());
                if (i < randomExportList.size()){
                    map.put(RandomCodeEnum.RANDOM_EXPORT.getDesc(), randomExportList.get(i));
                }else {
                    map.put(RandomCodeEnum.RANDOM_EXPORT.getDesc(), null);
                }
                mapList.add(map);
                i++;
            }
            for (int j = 0; j < randomExportList.size(); j++) {
                Map<String, Object> map = new LinkedHashMap<>();
                map.put(RandomCodeEnum.RANDOM_AFTER.getDesc(), randomExportList.get(j));
                map.put(RandomCodeEnum.ZM.getDesc(), null);
                map.put(RandomCodeEnum.RANDOM_IMPORT.getDesc(), null);
                map.put(RandomCodeEnum.NUM.getDesc(), null);
                map.put(RandomCodeEnum.RANDOM_EXPORT.getDesc(), null);
                mapList.add(map);
            }
        }else {
            int j = 0;//输出的所有的随机码那一列中，添加输出的随机码记录。该数字为记录了多少行
            for (int i = 0; i < randomExportList.size(); i++) {
                Map<String, Object> map = new LinkedHashMap<>();
                if (i < randomCodeList.size()){
                    map.put(RandomCodeEnum.RANDOM_AFTER.getDesc(), randomCodeList.get(i).getRandomAfter());
                    map.put(RandomCodeEnum.ZM.getDesc(), randomCodeList.get(i).getZm());
                    map.put(RandomCodeEnum.RANDOM_IMPORT.getDesc(), randomCodeList.get(i).getRandomImport());
                    map.put(RandomCodeEnum.NUM.getDesc(), randomCodeList.get(i).getNum());
                }else {
                    map.put(RandomCodeEnum.RANDOM_AFTER.getDesc(), randomExportList.get(j));
                    j++;
                    map.put(RandomCodeEnum.ZM.getDesc(), null);
                    map.put(RandomCodeEnum.RANDOM_IMPORT.getDesc(), null);
                    map.put(RandomCodeEnum.NUM.getDesc(), null);
                }
                map.put(RandomCodeEnum.RANDOM_EXPORT.getDesc(), randomExportList.get(i));
                mapList.add(map);
            }
            while (j < randomExportList.size()){
                Map<String, Object> map = new LinkedHashMap<>();
                map.put(RandomCodeEnum.RANDOM_AFTER.getDesc(), randomExportList.get(j));
                map.put(RandomCodeEnum.ZM.getDesc(), null);
                map.put(RandomCodeEnum.RANDOM_IMPORT.getDesc(), null);
                map.put(RandomCodeEnum.NUM.getDesc(), null);
                map.put(RandomCodeEnum.RANDOM_EXPORT.getDesc(), null);
                j++;
                mapList.add(map);
            }

        }


//        String sheetName = "物料编码对应表 (带具体机型)";
        ExcelWriter excelWriter = ExcelUtil.getWriter(true);
//        excelWriter.setCurrentRow(1);
        excelWriter.write(mapList, true);
//        excelWriter.renameSheet(sheetName);
        excelWriter.autoSizeColumnAll();
        excelWriter.flush(outputStream, true);
    }

    private static void random ( int i, int num, String randomImport, List <String> ziMuList,
                                 List < String > randomExportList, Random random, List <String> randomAfterList){
        while (i < num) {
            String randomExportRow = "";
            //分解randomImport的字母
            List<String> randomImportSplitList = new ArrayList<>(Arrays.asList(randomImport.split("")));
            for (String zRow : randomImportSplitList) {
                if (zRow.equals("?")) {
                    zRow = ziMuList.get(random.nextInt(ziMuList.size() - 1));
                }
                randomExportRow += zRow;
            }
            //当输出的结果List和历史的以前的结果集里面没有就添加
            if (!randomExportList.contains(randomExportRow) && !randomAfterList.contains(randomExportRow)) {
                randomExportList.add(randomExportRow);
                i++;
            }
        }
    }

    private void notRandom(List<RandomCode> randomCodeNotNullList, List<String> ziMuList, List<String> randomExportList, List<String> randomAfterList) {
        for (RandomCode randomCode : randomCodeNotNullList) {
            //分解randomImport的字母
            List<String> randomImportSplitList = new ArrayList<>(Arrays.asList(randomCode.getRandomImport().split("")));
            for (int j = 0; j < ziMuList.size(); j++) {//循环第一个问号的字母
                for (int two = 0; two < ziMuList.size(); two++) {//循环第二个问号的字母
                    String randomExportRow = "";
                    int i = 0;//判断是第几次识别到?
                    for (String zRow : randomImportSplitList) {
                        if (zRow.equals("?")) {
                            i = i + 1;//识别到?加一次
                            //每第一个?都要循环使用完所有字母
                            if (i == 1){
                                //如果是第一次识别到?就先使用一个字母,这个位置要使用完所有字母
                                zRow = ziMuList.get(j);
                            }else {
                                zRow = ziMuList.get(two);
                            }
                        }
                        randomExportRow += zRow;
                    }
                    //当输出的结果List和历史的以前的结果集里面没有就添加
                    if (!randomExportList.contains(randomExportRow) && !randomAfterList.contains(randomExportRow)) {
                        randomExportList.add(randomExportRow);
                    }
                }
            }

        }
    }
}
